import os
import random

import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'travel_recommend.settings')
django.setup()
from user.serializers import User, UserModelSerializer, UserComments, UserCommentsSerializer
from travel.serializers import Travel, TravelModelSerializer
import operator


class ItemBasedCF:
    def __init__(self):
        # 记录景点被多少用户评价过，N[1] = 10 代表有10个用户评价过id为1的景点
        self.N = {}
        # 相似矩阵，存储两个用户的相似度，如W[1][2] = 0.66 代表id为1的电影和id为2的电影相似度为0.66
        self.W = {}
        # 用户记录数据集中的数据，即用户最多评价的景点数据集
        self.train = {}
        # 使用最相似的k个景点
        self.k = 30
        # 为用户推挤n个景点
        self.n = 10

    def parse_data(self, comments):
        for i, line in enumerate(comments, 0):
            user_id = line['user_id']
            travel_id = line['travel_id']
            score = line['score']

            self.train.setdefault(user_id, [])
            self.train[user_id].append([travel_id, score])
        # print(self.train)

    def similarity(self):
        for user, item in self.train.items():
            items = [x[0] for x in item]
            for i in items:
                self.N.setdefault(i, 0)
                self.N[i] += 1
                for j in items:
                    if i != j:
                        self.W.setdefault(i, {})
                        self.W[i].setdefault(j, 0)
                        self.W[i][j] += 1
        for i, j_cnt in self.W.items():
            for j, cnt in j_cnt.items():
                self.W[i][j] = self.W[i][j] / (self.N[i] * self.N[j]) ** 0.5
        # print(self.W)

    def recommend(self, userId):
        rank = {}
        watched_items = [x[0] for x in self.train[userId]]

        for i in watched_items:
            for j, similar in sorted(self.W[i].items(), key=operator.itemgetter(1), reverse=True)[0:self.k]:
                if j not in watched_items:
                    rank.setdefault(j, 0)
                    rank[j] += float(self.train[userId][watched_items.index(i)][1]) * similar
        return sorted(rank.items(), key=operator.itemgetter(1), reverse=True)[0:self.n]


def recommend_item_data(user_id):
    itemClass = ItemBasedCF()
    comments = list(UserComments.objects.all().values())
    itemClass.parse_data(comments)
    itemClass.similarity()
    recommend_result = itemClass.recommend(user_id)
    res = []
    for travel_id, similar in recommend_result:
        travel = TravelModelSerializer(Travel.objects.get(id=travel_id)).data
        res.append(travel)
    return res


if __name__ == '__main__':
    itemClass = ItemBasedCF()
    comments = list(UserComments.objects.all().values())
    itemClass.parse_data(comments)
    itemClass.similarity()
    recommend_result = itemClass.recommend(33)
    print(recommend_result)
    # res = []
    # for travel_id, similar in recommend_result:
    #     travel = TravelModelSerializer(Travel.objects.get(id=travel_id))
    #     res.append(travel)
